/*
* Created on Oct 26, 2004
*
* Copyright (C) 2003
*
* $Id: PlaySound.java,v 1.3 2005/05/08 13:37:28 cawe Exp $
*/
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
using System;
using Globals = Suake2.UI.Globals;
using Math3D = Suake2.UI.util.Math3D;
namespace Suake2.UI.sound.joal
{
	
	/// <summary> PlaySound
	/// 
	/// </summary>
	/// <author>  cwei
	/// </author>
	public class PlaySound
	{
		
		internal const int MAX_PLAYSOUNDS = 128;
		
		// list with sentinel
		private static PlaySound freeList;
		private static PlaySound playableList;
		
		private static PlaySound[] backbuffer = new PlaySound[MAX_PLAYSOUNDS];
		
		// sound attributes
		internal int type;
		internal int entnum;
		internal int entchannel;
		internal int bufferId;
		internal float volume;
		internal float attenuation;
		internal float[] origin = new float[]{0, 0, 0};
		
		// begin time in ms
		private long beginTime;
		
		// for linked list
		private PlaySound prev, next;
		
		private PlaySound()
		{
			prev = next = null;
			this.clear();
		}
		
		private void  clear()
		{
			type = bufferId = entnum = entchannel = - 1;
			// volume = attenuation = beginTime = 0;
			attenuation = beginTime = 0;
			// Math3D.VectorClear(origin);
		}
		
		internal static void  reset()
		{
			// init the sentinels
			freeList.next = freeList.prev = freeList;
			playableList.next = playableList.prev = playableList;
			
			// concat the the freeList
			PlaySound ps;
			for (int i = 0; i < backbuffer.Length; i++)
			{
				ps = backbuffer[i];
				ps.clear();
				ps.prev = freeList;
				ps.next = freeList.next;
				ps.prev.next = ps;
				ps.next.prev = ps;
			}
		}
		
		internal static PlaySound nextPlayableSound()
		{
			PlaySound ps = null;
			while (true)
			{
				ps = playableList.next;
				if (ps == playableList || ps.beginTime > Globals.cl.time)
					return null;
				PlaySound.release(ps);
				return ps;
			}
		}
		
		private static PlaySound get_Renamed()
		{
			PlaySound ps = freeList.next;
			if (ps == freeList)
				return null;
			
			ps.prev.next = ps.next;
			ps.next.prev = ps.prev;
			return ps;
		}
		
		private static void  add(PlaySound ps)
		{
			
			PlaySound sort = playableList.next;
			
			for (; sort != playableList && sort.beginTime < ps.beginTime; sort = sort.next)
				;
			ps.next = sort;
			ps.prev = sort.prev;
			ps.next.prev = ps;
			ps.prev.next = ps;
		}
		
		private static void  release(PlaySound ps)
		{
			ps.prev.next = ps.next;
			ps.next.prev = ps.prev;
			// add to free list
			ps.next = freeList.next;
			freeList.next.prev = ps;
			ps.prev = freeList;
			freeList.next = ps;
		}
		
		internal static void  allocate(float[] origin, int entnum, int entchannel, int bufferId, float volume, float attenuation, float timeoffset)
		{
			
			PlaySound ps = PlaySound.get_Renamed();
			
			if (ps != null)
			{
				// find the right sound type
				if (entnum == Globals.cl.playernum + 1)
				{
					ps.type = Channel.LISTENER;
				}
				else if (origin != null)
				{
					ps.type = Channel.FIXED;
					Math3D.VectorCopy(origin, ps.origin);
				}
				else
				{
					ps.type = Channel.DYNAMIC;
				}
				ps.entnum = entnum;
				ps.entchannel = entchannel;
				ps.bufferId = bufferId;
				ps.volume = volume;
				ps.attenuation = attenuation;
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				ps.beginTime = Globals.cl.time + (long) (timeoffset * 1000);
				PlaySound.add(ps);
			}
			else
			{
				System.Console.Error.WriteLine("PlaySounds out of Limit");
			}
		}
		static PlaySound()
		{
			{
				for (int i = 0; i < backbuffer.Length; i++)
				{
					backbuffer[i] = new PlaySound();
				}
				// init the sentinels
				freeList = new PlaySound();
				playableList = new PlaySound();
				// reset the lists
				reset();
			}
		}
	}
}